/*
 * Aritmetico.h
 *
 *  Created on: Apr 2, 2012
 *      Author: damian
 */
#include <iostream>
#include <list>
#include "inttypes.h"
#include "../PPMC/Modelo.h"
#include "ICompresor.h"
#include "../PPMC/CompresorAritmeticoBase.h"
#include "BitProcessor.h"

#ifndef ARITMETICO_H_
#define ARITMETICO_H_

using namespace std;

typedef struct
{
    uint32_t inicio;
    uint32_t fin;
    uint32_t total;
} SimboloAritmetico; // [frec_inicio, frec_fin)

class Aritmetico: public ICompresor
{
    uint32_t underflowCounter;
    uint32_t inicio;
    uint32_t fin;
    uint32_t codigo;
    BitProcessor bp;
    bool primeraLlamada;
    void comprimir(SimboloAritmetico simbolo, ostream & salida);
    void actualizarLimites(SimboloAritmetico);
    void renormalizar(ostream & salida);
    void flush_comprimir(ostream & salida);
    uint32_t descomprimir(SimboloAritmetico simbolo, istream & entrada);
    uint32_t calcularFrecuenciaLeida(SimboloAritmetico s);
    uint32_t calcularFrecuenciaTotal(FrecuenciasSimbolos frecuencias, FrecuenciasSimbolos excluir);
    void quitarCaracterDescomprimido(SimboloAritmetico s, istream & entrada);
public:
    Aritmetico();
    virtual ~Aritmetico();
    virtual void comprimir(const Simbolo simbolo, const FrecuenciasSimbolos & frecuencias, const FrecuenciasSimbolos & excluir, std::ostream & salida);
    virtual void comprimirEquiprovable(const Simbolo simbolo, const FrecuenciasSimbolos & frecuencias, std::ostream & salida);
    virtual Simbolo descomprimir(const FrecuenciasSimbolos & frecuencias, const FrecuenciasSimbolos & excluir, std::istream & entrada);
    virtual Simbolo descomprimirEquiprovable(const FrecuenciasSimbolos & frecuencias, std::istream & entrada);
    static const uint32_t ULTIMO_BIT_UNO = 0x000000001;
    static const uint32_t UNOS_BIT = 0xFFFFFFFF;
    static const uint32_t CERO_BITS =0x00000000;
    static const uint32_t TODOS_MENOS_DOS_PRIMEROS_BITS = 0x3fffFFFF;
    static const uint32_t SEGUNDO_BIT = 0x40000000;
    static const uint32_t PRIMER_BIT =  0x80000000;

};

#endif /* ARITMETICO_H_ */
